home *** CD-ROM | disk | FTP | other *** search
/ Introduction to 3D Game …ogramming with DirectX 12 / Introduction-to-3D-Game-Programming-with-DirectX-12.ISO / Code.Textures / Chapter 15 First Person Camera and Dynamic Indexing / CameraAndDynamicIndexing / CameraAndDynamicIndexingApp.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2016-03-02  |  36.8 KB  |  966 lines

  1. //***************************************************************************************
  2. // CameraAndDynamicIndexingApp.cpp by Frank Luna (C) 2015 All Rights Reserved.
  3. //***************************************************************************************
  4.  
  5. #include "../../Common/d3dApp.h"
  6. #include "../../Common/MathHelper.h"
  7. #include "../../Common/UploadBuffer.h"
  8. #include "../../Common/GeometryGenerator.h"
  9. #include "../../Common/Camera.h"
  10. #include "FrameResource.h"
  11.  
  12. using Microsoft::WRL::ComPtr;
  13. using namespace DirectX;
  14. using namespace DirectX::PackedVector;
  15.  
  16. #pragma comment(lib, "d3dcompiler.lib")
  17. #pragma comment(lib, "D3D12.lib")
  18.  
  19. const int gNumFrameResources = 3;
  20.  
  21. // Lightweight structure stores parameters to draw a shape.  This will
  22. // vary from app-to-app.
  23. struct RenderItem
  24. {
  25.     RenderItem() = default;
  26.     RenderItem(const RenderItem& rhs) = delete;
  27.  
  28.     // World matrix of the shape that describes the object's local space
  29.     // relative to the world space, which defines the position, orientation,
  30.     // and scale of the object in the world.
  31.     XMFLOAT4X4 World = MathHelper::Identity4x4();
  32.  
  33.     XMFLOAT4X4 TexTransform = MathHelper::Identity4x4();
  34.  
  35.     // Dirty flag indicating the object data has changed and we need to update the constant buffer.
  36.     // Because we have an object cbuffer for each FrameResource, we have to apply the
  37.     // update to each FrameResource.  Thus, when we modify obect data we should set 
  38.     // NumFramesDirty = gNumFrameResources so that each frame resource gets the update.
  39.     int NumFramesDirty = gNumFrameResources;
  40.  
  41.     // Index into GPU constant buffer corresponding to the ObjectCB for this render item.
  42.     UINT ObjCBIndex = -1;
  43.  
  44.     Material* Mat = nullptr;
  45.     MeshGeometry* Geo = nullptr;
  46.  
  47.     // Primitive topology.
  48.     D3D12_PRIMITIVE_TOPOLOGY PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  49.  
  50.     // DrawIndexedInstanced parameters.
  51.     UINT IndexCount = 0;
  52.     UINT StartIndexLocation = 0;
  53.     int BaseVertexLocation = 0;
  54. };
  55.  
  56. class CameraAndDynamicIndexingApp : public D3DApp
  57. {
  58. public:
  59.     CameraAndDynamicIndexingApp(HINSTANCE hInstance);
  60.     CameraAndDynamicIndexingApp(const CameraAndDynamicIndexingApp& rhs) = delete;
  61.     CameraAndDynamicIndexingApp& operator=(const CameraAndDynamicIndexingApp& rhs) = delete;
  62.     ~CameraAndDynamicIndexingApp();
  63.  
  64.     virtual bool Initialize()override;
  65.  
  66. private:
  67.     virtual void OnResize()override;
  68.     virtual void Update(const GameTimer& gt)override;
  69.     virtual void Draw(const GameTimer& gt)override;
  70.  
  71.     virtual void OnMouseDown(WPARAM btnState, int x, int y)override;
  72.     virtual void OnMouseUp(WPARAM btnState, int x, int y)override;
  73.     virtual void OnMouseMove(WPARAM btnState, int x, int y)override;
  74.  
  75.     void OnKeyboardInput(const GameTimer& gt);
  76.     void AnimateMaterials(const GameTimer& gt);
  77.     void UpdateObjectCBs(const GameTimer& gt);
  78.     void UpdateMaterialBuffer(const GameTimer& gt);
  79.     void UpdateMainPassCB(const GameTimer& gt);
  80.  
  81.     void LoadTextures();
  82.     void BuildRootSignature();
  83.     void BuildDescriptorHeaps();
  84.     void BuildShadersAndInputLayout();
  85.     void BuildShapeGeometry();
  86.     void BuildPSOs();
  87.     void BuildFrameResources();
  88.     void BuildMaterials();
  89.     void BuildRenderItems();
  90.     void DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems);
  91.  
  92.     std::array<const CD3DX12_STATIC_SAMPLER_DESC, 6> GetStaticSamplers();
  93.  
  94. private:
  95.  
  96.     std::vector<std::unique_ptr<FrameResource>> mFrameResources;
  97.     FrameResource* mCurrFrameResource = nullptr;
  98.     int mCurrFrameResourceIndex = 0;
  99.  
  100.     UINT mCbvSrvDescriptorSize = 0;
  101.  
  102.     ComPtr<ID3D12RootSignature> mRootSignature = nullptr;
  103.  
  104.     ComPtr<ID3D12DescriptorHeap> mSrvDescriptorHeap = nullptr;
  105.  
  106.     std::unordered_map<std::string, std::unique_ptr<MeshGeometry>> mGeometries;
  107.     std::unordered_map<std::string, std::unique_ptr<Material>> mMaterials;
  108.     std::unordered_map<std::string, std::unique_ptr<Texture>> mTextures;
  109.     std::unordered_map<std::string, ComPtr<ID3DBlob>> mShaders;
  110.     std::unordered_map<std::string, ComPtr<ID3D12PipelineState>> mPSOs;
  111.  
  112.     std::vector<D3D12_INPUT_ELEMENT_DESC> mInputLayout;
  113.  
  114.     // List of all the render items.
  115.     std::vector<std::unique_ptr<RenderItem>> mAllRitems;
  116.  
  117.     // Render items divided by PSO.
  118.     std::vector<RenderItem*> mOpaqueRitems;
  119.  
  120.     PassConstants mMainPassCB;
  121.  
  122.     Camera mCamera;
  123.  
  124.     POINT mLastMousePos;
  125. };
  126.  
  127. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
  128.     PSTR cmdLine, int showCmd)
  129. {
  130.     // Enable run-time memory check for debug builds.
  131. #if defined(DEBUG) | defined(_DEBUG)
  132.     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  133. #endif
  134.  
  135.     try
  136.     {
  137.         CameraAndDynamicIndexingApp theApp(hInstance);
  138.         if(!theApp.Initialize())
  139.             return 0;
  140.  
  141.         return theApp.Run();
  142.     }
  143.     catch(DxException& e)
  144.     {
  145.         MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
  146.         return 0;
  147.     }
  148. }
  149.  
  150. CameraAndDynamicIndexingApp::CameraAndDynamicIndexingApp(HINSTANCE hInstance)
  151.     : D3DApp(hInstance)
  152. {
  153. }
  154.  
  155. CameraAndDynamicIndexingApp::~CameraAndDynamicIndexingApp()
  156. {
  157.     if(md3dDevice != nullptr)
  158.         FlushCommandQueue();
  159. }
  160.  
  161. bool CameraAndDynamicIndexingApp::Initialize()
  162. {
  163.     if(!D3DApp::Initialize())
  164.         return false;
  165.  
  166.     // Reset the command list to prep for initialization commands.
  167.     ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), nullptr));
  168.  
  169.     // Get the increment size of a descriptor in this heap type.  This is hardware specific, 
  170.     // so we have to query this information.
  171.     mCbvSrvDescriptorSize = md3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
  172.  
  173.     mCamera.SetPosition(0.0f, 2.0f, -15.0f);
  174.  
  175.     LoadTextures();
  176.     BuildRootSignature();
  177.     BuildDescriptorHeaps();
  178.     BuildShadersAndInputLayout();
  179.     BuildShapeGeometry();
  180.     BuildMaterials();
  181.     BuildRenderItems();
  182.     BuildFrameResources();
  183.     BuildPSOs();
  184.  
  185.     // Execute the initialization commands.
  186.     ThrowIfFailed(mCommandList->Close());
  187.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  188.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  189.  
  190.     // Wait until initialization is complete.
  191.     FlushCommandQueue();
  192.  
  193.     return true;
  194. }
  195.  
  196. void CameraAndDynamicIndexingApp::OnResize()
  197. {
  198.     D3DApp::OnResize();
  199.  
  200.     mCamera.SetLens(0.25f*MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
  201. }
  202.  
  203. void CameraAndDynamicIndexingApp::Update(const GameTimer& gt)
  204. {
  205.     OnKeyboardInput(gt);
  206.  
  207.     // Cycle through the circular frame resource array.
  208.     mCurrFrameResourceIndex = (mCurrFrameResourceIndex + 1) % gNumFrameResources;
  209.     mCurrFrameResource = mFrameResources[mCurrFrameResourceIndex].get();
  210.  
  211.     // Has the GPU finished processing the commands of the current frame resource?
  212.     // If not, wait until the GPU has completed commands up to this fence point.
  213.     if(mCurrFrameResource->Fence != 0 && mFence->GetCompletedValue() < mCurrFrameResource->Fence)
  214.     {
  215.         HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);
  216.         ThrowIfFailed(mFence->SetEventOnCompletion(mCurrFrameResource->Fence, eventHandle));
  217.         WaitForSingleObject(eventHandle, INFINITE);
  218.         CloseHandle(eventHandle);
  219.     }
  220.  
  221.     AnimateMaterials(gt);
  222.     UpdateObjectCBs(gt);
  223.     UpdateMaterialBuffer(gt);
  224.     UpdateMainPassCB(gt);
  225. }
  226.  
  227. void CameraAndDynamicIndexingApp::Draw(const GameTimer& gt)
  228. {
  229.     auto cmdListAlloc = mCurrFrameResource->CmdListAlloc;
  230.  
  231.     // Reuse the memory associated with command recording.
  232.     // We can only reset when the associated command lists have finished execution on the GPU.
  233.     ThrowIfFailed(cmdListAlloc->Reset());
  234.  
  235.     // A command list can be reset after it has been added to the command queue via ExecuteCommandList.
  236.     // Reusing the command list reuses memory.
  237.     ThrowIfFailed(mCommandList->Reset(cmdListAlloc.Get(), mPSOs["opaque"].Get()));
  238.  
  239.     mCommandList->RSSetViewports(1, &mScreenViewport);
  240.     mCommandList->RSSetScissorRects(1, &mScissorRect);
  241.  
  242.     // Indicate a state transition on the resource usage.
  243.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  244.         D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
  245.  
  246.     // Clear the back buffer and depth buffer.
  247.     mCommandList->ClearRenderTargetView(CurrentBackBufferView(), Colors::LightSteelBlue, 0, nullptr);
  248.     mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
  249.  
  250.     // Specify the buffers we are going to render to.
  251.     mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView());
  252.  
  253.     ID3D12DescriptorHeap* descriptorHeaps[] = { mSrvDescriptorHeap.Get() };
  254.     mCommandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps);
  255.  
  256.     mCommandList->SetGraphicsRootSignature(mRootSignature.Get());
  257.  
  258.     auto passCB = mCurrFrameResource->PassCB->Resource();
  259.     mCommandList->SetGraphicsRootConstantBufferView(1, passCB->GetGPUVirtualAddress());
  260.  
  261.     // Bind all the materials used in this scene.  For structured buffers, we can bypass the heap and 
  262.     // set as a root descriptor.
  263.     auto matBuffer = mCurrFrameResource->MaterialBuffer->Resource();
  264.     mCommandList->SetGraphicsRootShaderResourceView(2, matBuffer->GetGPUVirtualAddress());
  265.  
  266.     // Bind all the textures used in this scene.  Observe
  267.     // that we only have to specify the first descriptor in the table.  
  268.     // The root signature knows how many descriptors are expected in the table.
  269.     mCommandList->SetGraphicsRootDescriptorTable(3, mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  270.  
  271.     DrawRenderItems(mCommandList.Get(), mOpaqueRitems);
  272.  
  273.     // Indicate a state transition on the resource usage.
  274.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  275.         D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
  276.  
  277.     // Done recording commands.
  278.     ThrowIfFailed(mCommandList->Close());
  279.  
  280.     // Add the command list to the queue for execution.
  281.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  282.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  283.  
  284.     // Swap the back and front buffers
  285.     ThrowIfFailed(mSwapChain->Present(0, 0));
  286.     mCurrBackBuffer = (mCurrBackBuffer + 1) % SwapChainBufferCount;
  287.  
  288.     // Advance the fence value to mark commands up to this fence point.
  289.     mCurrFrameResource->Fence = ++mCurrentFence;
  290.  
  291.     // Add an instruction to the command queue to set a new fence point. 
  292.     // Because we are on the GPU timeline, the new fence point won't be 
  293.     // set until the GPU finishes processing all the commands prior to this Signal().
  294.     mCommandQueue->Signal(mFence.Get(), mCurrentFence);
  295. }
  296.  
  297. void CameraAndDynamicIndexingApp::OnMouseDown(WPARAM btnState, int x, int y)
  298. {
  299.     mLastMousePos.x = x;
  300.     mLastMousePos.y = y;
  301.  
  302.     SetCapture(mhMainWnd);
  303. }
  304.  
  305. void CameraAndDynamicIndexingApp::OnMouseUp(WPARAM btnState, int x, int y)
  306. {
  307.     ReleaseCapture();
  308. }
  309.  
  310. void CameraAndDynamicIndexingApp::OnMouseMove(WPARAM btnState, int x, int y)
  311. {
  312.     if((btnState & MK_LBUTTON) != 0)
  313.     {
  314.         // Make each pixel correspond to a quarter of a degree.
  315.         float dx = XMConvertToRadians(0.25f*static_cast<float>(x - mLastMousePos.x));
  316.         float dy = XMConvertToRadians(0.25f*static_cast<float>(y - mLastMousePos.y));
  317.  
  318.         mCamera.Pitch(dy);
  319.         mCamera.RotateY(dx);
  320.     }
  321.  
  322.     mLastMousePos.x = x;
  323.     mLastMousePos.y = y;
  324. }
  325.  
  326. void CameraAndDynamicIndexingApp::OnKeyboardInput(const GameTimer& gt)
  327. {
  328.     const float dt = gt.DeltaTime();
  329.  
  330.     if(GetAsyncKeyState('W') & 0x8000)
  331.         mCamera.Walk(10.0f*dt);
  332.  
  333.     if(GetAsyncKeyState('S') & 0x8000)
  334.         mCamera.Walk(-10.0f*dt);
  335.  
  336.     if(GetAsyncKeyState('A') & 0x8000)
  337.         mCamera.Strafe(-10.0f*dt);
  338.  
  339.     if(GetAsyncKeyState('D') & 0x8000)
  340.         mCamera.Strafe(10.0f*dt);
  341.  
  342.     mCamera.UpdateViewMatrix();
  343. }
  344.  
  345. void CameraAndDynamicIndexingApp::AnimateMaterials(const GameTimer& gt)
  346. {
  347.     
  348. }
  349.  
  350. void CameraAndDynamicIndexingApp::UpdateObjectCBs(const GameTimer& gt)
  351. {
  352.     auto currObjectCB = mCurrFrameResource->ObjectCB.get();
  353.     for(auto& e : mAllRitems)
  354.     {
  355.         // Only update the cbuffer data if the constants have changed.  
  356.         // This needs to be tracked per frame resource.
  357.         if(e->NumFramesDirty > 0)
  358.         {
  359.             XMMATRIX world = XMLoadFloat4x4(&e->World);
  360.             XMMATRIX texTransform = XMLoadFloat4x4(&e->TexTransform);
  361.  
  362.             ObjectConstants objConstants;
  363.             XMStoreFloat4x4(&objConstants.World, XMMatrixTranspose(world));
  364.             XMStoreFloat4x4(&objConstants.TexTransform, XMMatrixTranspose(texTransform));
  365.             objConstants.MaterialIndex = e->Mat->MatCBIndex;
  366.  
  367.             currObjectCB->CopyData(e->ObjCBIndex, objConstants);
  368.  
  369.             // Next FrameResource need to be updated too.
  370.             e->NumFramesDirty--;
  371.         }
  372.     }
  373. }
  374.  
  375. void CameraAndDynamicIndexingApp::UpdateMaterialBuffer(const GameTimer& gt)
  376. {
  377.     auto currMaterialBuffer = mCurrFrameResource->MaterialBuffer.get();
  378.     for(auto& e : mMaterials)
  379.     {
  380.         // Only update the cbuffer data if the constants have changed.  If the cbuffer
  381.         // data changes, it needs to be updated for each FrameResource.
  382.         Material* mat = e.second.get();
  383.         if(mat->NumFramesDirty > 0)
  384.         {
  385.             XMMATRIX matTransform = XMLoadFloat4x4(&mat->MatTransform);
  386.  
  387.             MaterialData matData;
  388.             matData.DiffuseAlbedo = mat->DiffuseAlbedo;
  389.             matData.FresnelR0 = mat->FresnelR0;
  390.             matData.Roughness = mat->Roughness;
  391.             XMStoreFloat4x4(&matData.MatTransform, XMMatrixTranspose(matTransform));
  392.             matData.DiffuseMapIndex = mat->DiffuseSrvHeapIndex;
  393.  
  394.             currMaterialBuffer->CopyData(mat->MatCBIndex, matData);
  395.  
  396.             // Next FrameResource need to be updated too.
  397.             mat->NumFramesDirty--;
  398.         }
  399.     }
  400. }
  401.  
  402. void CameraAndDynamicIndexingApp::UpdateMainPassCB(const GameTimer& gt)
  403. {
  404.     XMMATRIX view = mCamera.GetView();
  405.     XMMATRIX proj = mCamera.GetProj();
  406.  
  407.     XMMATRIX viewProj = XMMatrixMultiply(view, proj);
  408.     XMMATRIX invView = XMMatrixInverse(&XMMatrixDeterminant(view), view);
  409.     XMMATRIX invProj = XMMatrixInverse(&XMMatrixDeterminant(proj), proj);
  410.     XMMATRIX invViewProj = XMMatrixInverse(&XMMatrixDeterminant(viewProj), viewProj);
  411.  
  412.     XMStoreFloat4x4(&mMainPassCB.View, XMMatrixTranspose(view));
  413.     XMStoreFloat4x4(&mMainPassCB.InvView, XMMatrixTranspose(invView));
  414.     XMStoreFloat4x4(&mMainPassCB.Proj, XMMatrixTranspose(proj));
  415.     XMStoreFloat4x4(&mMainPassCB.InvProj, XMMatrixTranspose(invProj));
  416.     XMStoreFloat4x4(&mMainPassCB.ViewProj, XMMatrixTranspose(viewProj));
  417.     XMStoreFloat4x4(&mMainPassCB.InvViewProj, XMMatrixTranspose(invViewProj));
  418.     mMainPassCB.EyePosW = mCamera.GetPosition3f();
  419.     mMainPassCB.RenderTargetSize = XMFLOAT2((float)mClientWidth, (float)mClientHeight);
  420.     mMainPassCB.InvRenderTargetSize = XMFLOAT2(1.0f / mClientWidth, 1.0f / mClientHeight);
  421.     mMainPassCB.NearZ = 1.0f;
  422.     mMainPassCB.FarZ = 1000.0f;
  423.     mMainPassCB.TotalTime = gt.TotalTime();
  424.     mMainPassCB.DeltaTime = gt.DeltaTime();
  425.     mMainPassCB.AmbientLight = { 0.25f, 0.25f, 0.35f, 1.0f };
  426.     mMainPassCB.Lights[0].Direction = { 0.57735f, -0.57735f, 0.57735f };
  427.     mMainPassCB.Lights[0].Strength = { 0.8f, 0.8f, 0.8f };
  428.     mMainPassCB.Lights[1].Direction = { -0.57735f, -0.57735f, 0.57735f };
  429.     mMainPassCB.Lights[1].Strength = { 0.4f, 0.4f, 0.4f };
  430.     mMainPassCB.Lights[2].Direction = { 0.0f, -0.707f, -0.707f };
  431.     mMainPassCB.Lights[2].Strength = { 0.2f, 0.2f, 0.2f };
  432.  
  433.     auto currPassCB = mCurrFrameResource->PassCB.get();
  434.     currPassCB->CopyData(0, mMainPassCB);
  435. }
  436.  
  437. void CameraAndDynamicIndexingApp::LoadTextures()
  438. {
  439.     auto bricksTex = std::make_unique<Texture>();
  440.     bricksTex->Name = "bricksTex";
  441.     bricksTex->Filename = L"../../Textures/bricks.dds";
  442.     ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
  443.         mCommandList.Get(), bricksTex->Filename.c_str(),
  444.         bricksTex->Resource, bricksTex->UploadHeap));
  445.  
  446.     auto stoneTex = std::make_unique<Texture>();
  447.     stoneTex->Name = "stoneTex";
  448.     stoneTex->Filename = L"../../Textures/stone.dds";
  449.     ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
  450.         mCommandList.Get(), stoneTex->Filename.c_str(),
  451.         stoneTex->Resource, stoneTex->UploadHeap));
  452.  
  453.     auto tileTex = std::make_unique<Texture>();
  454.     tileTex->Name = "tileTex";
  455.     tileTex->Filename = L"../../Textures/tile.dds";
  456.     ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
  457.         mCommandList.Get(), tileTex->Filename.c_str(),
  458.         tileTex->Resource, tileTex->UploadHeap));
  459.  
  460.     auto crateTex = std::make_unique<Texture>();
  461.     crateTex->Name = "crateTex";
  462.     crateTex->Filename = L"../../Textures/WoodCrate01.dds";
  463.     ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
  464.         mCommandList.Get(), crateTex->Filename.c_str(),
  465.         crateTex->Resource, crateTex->UploadHeap));
  466.  
  467.     mTextures[bricksTex->Name] = std::move(bricksTex);
  468.     mTextures[stoneTex->Name] = std::move(stoneTex);
  469.     mTextures[tileTex->Name] = std::move(tileTex);
  470.     mTextures[crateTex->Name] = std::move(crateTex);
  471. }
  472.  
  473. void CameraAndDynamicIndexingApp::BuildRootSignature()
  474. {
  475.     CD3DX12_DESCRIPTOR_RANGE texTable;
  476.     texTable.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 4, 0, 0);
  477.  
  478.     // Root parameter can be a table, root descriptor or root constants.
  479.     CD3DX12_ROOT_PARAMETER slotRootParameter[4];
  480.  
  481.     // Perfomance TIP: Order from most frequent to least frequent.
  482.     slotRootParameter[0].InitAsConstantBufferView(0);
  483.     slotRootParameter[1].InitAsConstantBufferView(1);
  484.     slotRootParameter[2].InitAsShaderResourceView(0, 1);
  485.     slotRootParameter[3].InitAsDescriptorTable(1, &texTable, D3D12_SHADER_VISIBILITY_PIXEL);
  486.  
  487.  
  488.     auto staticSamplers = GetStaticSamplers();
  489.  
  490.     // A root signature is an array of root parameters.
  491.     CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(4, slotRootParameter,
  492.         (UINT)staticSamplers.size(), staticSamplers.data(),
  493.         D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
  494.  
  495.     // create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer
  496.     ComPtr<ID3DBlob> serializedRootSig = nullptr;
  497.     ComPtr<ID3DBlob> errorBlob = nullptr;
  498.     HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
  499.         serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());
  500.  
  501.     if(errorBlob != nullptr)
  502.     {
  503.         ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
  504.     }
  505.     ThrowIfFailed(hr);
  506.  
  507.     ThrowIfFailed(md3dDevice->CreateRootSignature(
  508.         0,
  509.         serializedRootSig->GetBufferPointer(),
  510.         serializedRootSig->GetBufferSize(),
  511.         IID_PPV_ARGS(mRootSignature.GetAddressOf())));
  512. }
  513.  
  514. void CameraAndDynamicIndexingApp::BuildDescriptorHeaps()
  515. {
  516.     //
  517.     // Create the SRV heap.
  518.     //
  519.     D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
  520.     srvHeapDesc.NumDescriptors = 4;
  521.     srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
  522.     srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
  523.     ThrowIfFailed(md3dDevice->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&mSrvDescriptorHeap)));
  524.  
  525.     //
  526.     // Fill out the heap with actual descriptors.
  527.     //
  528.     CD3DX12_CPU_DESCRIPTOR_HANDLE hDescriptor(mSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
  529.  
  530.     auto bricksTex = mTextures["bricksTex"]->Resource;
  531.     auto stoneTex = mTextures["stoneTex"]->Resource;
  532.     auto tileTex = mTextures["tileTex"]->Resource;
  533.     auto crateTex = mTextures["crateTex"]->Resource;
  534.  
  535.     D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
  536.     srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
  537.     srvDesc.Format = bricksTex->GetDesc().Format;
  538.     srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
  539.     srvDesc.Texture2D.MostDetailedMip = 0;
  540.     srvDesc.Texture2D.MipLevels = bricksTex->GetDesc().MipLevels;
  541.     srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
  542.     md3dDevice->CreateShaderResourceView(bricksTex.Get(), &srvDesc, hDescriptor);
  543.  
  544.     // next descriptor
  545.     hDescriptor.Offset(1, mCbvSrvDescriptorSize);
  546.  
  547.     srvDesc.Format = stoneTex->GetDesc().Format;
  548.     srvDesc.Texture2D.MipLevels = stoneTex->GetDesc().MipLevels;
  549.     md3dDevice->CreateShaderResourceView(stoneTex.Get(), &srvDesc, hDescriptor);
  550.  
  551.     // next descriptor
  552.     hDescriptor.Offset(1, mCbvSrvDescriptorSize);
  553.  
  554.     srvDesc.Format = tileTex->GetDesc().Format;
  555.     srvDesc.Texture2D.MipLevels = tileTex->GetDesc().MipLevels;
  556.     md3dDevice->CreateShaderResourceView(tileTex.Get(), &srvDesc, hDescriptor);
  557.  
  558.     // next descriptor
  559.     hDescriptor.Offset(1, mCbvSrvDescriptorSize);
  560.  
  561.     srvDesc.Format = crateTex->GetDesc().Format;
  562.     srvDesc.Texture2D.MipLevels = crateTex->GetDesc().MipLevels;
  563.     md3dDevice->CreateShaderResourceView(crateTex.Get(), &srvDesc, hDescriptor);
  564. }
  565.  
  566. void CameraAndDynamicIndexingApp::BuildShadersAndInputLayout()
  567. {
  568.     const D3D_SHADER_MACRO alphaTestDefines[] =
  569.     {
  570.         "ALPHA_TEST", "1",
  571.         NULL, NULL
  572.     };
  573.  
  574.     mShaders["standardVS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", nullptr, "VS", "vs_5_1");
  575.     mShaders["opaquePS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", nullptr, "PS", "ps_5_1");
  576.     
  577.     mInputLayout =
  578.     {
  579.         { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  580.         { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  581.         { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  582.     };
  583. }
  584.  
  585. void CameraAndDynamicIndexingApp::BuildShapeGeometry()
  586. {
  587.     GeometryGenerator geoGen;
  588.     GeometryGenerator::MeshData box = geoGen.CreateBox(1.0f, 1.0f, 1.0f, 3);
  589.     GeometryGenerator::MeshData grid = geoGen.CreateGrid(20.0f, 30.0f, 60, 40);
  590.     GeometryGenerator::MeshData sphere = geoGen.CreateSphere(0.5f, 20, 20);
  591.     GeometryGenerator::MeshData cylinder = geoGen.CreateCylinder(0.5f, 0.3f, 3.0f, 20, 20);
  592.  
  593.     //
  594.     // We are concatenating all the geometry into one big vertex/index buffer.  So
  595.     // define the regions in the buffer each submesh covers.
  596.     //
  597.  
  598.     // Cache the vertex offsets to each object in the concatenated vertex buffer.
  599.     UINT boxVertexOffset = 0;
  600.     UINT gridVertexOffset = (UINT)box.Vertices.size();
  601.     UINT sphereVertexOffset = gridVertexOffset + (UINT)grid.Vertices.size();
  602.     UINT cylinderVertexOffset = sphereVertexOffset + (UINT)sphere.Vertices.size();
  603.  
  604.     // Cache the starting index for each object in the concatenated index buffer.
  605.     UINT boxIndexOffset = 0;
  606.     UINT gridIndexOffset = (UINT)box.Indices32.size();
  607.     UINT sphereIndexOffset = gridIndexOffset + (UINT)grid.Indices32.size();
  608.     UINT cylinderIndexOffset = sphereIndexOffset + (UINT)sphere.Indices32.size();
  609.  
  610.     SubmeshGeometry boxSubmesh;
  611.     boxSubmesh.IndexCount = (UINT)box.Indices32.size();
  612.     boxSubmesh.StartIndexLocation = boxIndexOffset;
  613.     boxSubmesh.BaseVertexLocation = boxVertexOffset;
  614.  
  615.     SubmeshGeometry gridSubmesh;
  616.     gridSubmesh.IndexCount = (UINT)grid.Indices32.size();
  617.     gridSubmesh.StartIndexLocation = gridIndexOffset;
  618.     gridSubmesh.BaseVertexLocation = gridVertexOffset;
  619.  
  620.     SubmeshGeometry sphereSubmesh;
  621.     sphereSubmesh.IndexCount = (UINT)sphere.Indices32.size();
  622.     sphereSubmesh.StartIndexLocation = sphereIndexOffset;
  623.     sphereSubmesh.BaseVertexLocation = sphereVertexOffset;
  624.  
  625.     SubmeshGeometry cylinderSubmesh;
  626.     cylinderSubmesh.IndexCount = (UINT)cylinder.Indices32.size();
  627.     cylinderSubmesh.StartIndexLocation = cylinderIndexOffset;
  628.     cylinderSubmesh.BaseVertexLocation = cylinderVertexOffset;
  629.  
  630.     //
  631.     // Extract the vertex elements we are interested in and pack the
  632.     // vertices of all the meshes into one vertex buffer.
  633.     //
  634.  
  635.     auto totalVertexCount =
  636.         box.Vertices.size() +
  637.         grid.Vertices.size() +
  638.         sphere.Vertices.size() +
  639.         cylinder.Vertices.size();
  640.  
  641.     std::vector<Vertex> vertices(totalVertexCount);
  642.  
  643.     UINT k = 0;
  644.     for(size_t i = 0; i < box.Vertices.size(); ++i, ++k)
  645.     {
  646.         vertices[k].Pos = box.Vertices[i].Position;
  647.         vertices[k].Normal = box.Vertices[i].Normal;
  648.         vertices[k].TexC = box.Vertices[i].TexC;
  649.     }
  650.  
  651.     for(size_t i = 0; i < grid.Vertices.size(); ++i, ++k)
  652.     {
  653.         vertices[k].Pos = grid.Vertices[i].Position;
  654.         vertices[k].Normal = grid.Vertices[i].Normal;
  655.         vertices[k].TexC = grid.Vertices[i].TexC;
  656.     }
  657.  
  658.     for(size_t i = 0; i < sphere.Vertices.size(); ++i, ++k)
  659.     {
  660.         vertices[k].Pos = sphere.Vertices[i].Position;
  661.         vertices[k].Normal = sphere.Vertices[i].Normal;
  662.         vertices[k].TexC = sphere.Vertices[i].TexC;
  663.     }
  664.  
  665.     for(size_t i = 0; i < cylinder.Vertices.size(); ++i, ++k)
  666.     {
  667.         vertices[k].Pos = cylinder.Vertices[i].Position;
  668.         vertices[k].Normal = cylinder.Vertices[i].Normal;
  669.         vertices[k].TexC = cylinder.Vertices[i].TexC;
  670.     }
  671.  
  672.     std::vector<std::uint16_t> indices;
  673.     indices.insert(indices.end(), std::begin(box.GetIndices16()), std::end(box.GetIndices16()));
  674.     indices.insert(indices.end(), std::begin(grid.GetIndices16()), std::end(grid.GetIndices16()));
  675.     indices.insert(indices.end(), std::begin(sphere.GetIndices16()), std::end(sphere.GetIndices16()));
  676.     indices.insert(indices.end(), std::begin(cylinder.GetIndices16()), std::end(cylinder.GetIndices16()));
  677.  
  678.     const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
  679.     const UINT ibByteSize = (UINT)indices.size()  * sizeof(std::uint16_t);
  680.  
  681.     auto geo = std::make_unique<MeshGeometry>();
  682.     geo->Name = "shapeGeo";
  683.  
  684.     ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
  685.     CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
  686.  
  687.     ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
  688.     CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
  689.  
  690.     geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  691.         mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
  692.  
  693.     geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  694.         mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
  695.  
  696.     geo->VertexByteStride = sizeof(Vertex);
  697.     geo->VertexBufferByteSize = vbByteSize;
  698.     geo->IndexFormat = DXGI_FORMAT_R16_UINT;
  699.     geo->IndexBufferByteSize = ibByteSize;
  700.  
  701.     geo->DrawArgs["box"] = boxSubmesh;
  702.     geo->DrawArgs["grid"] = gridSubmesh;
  703.     geo->DrawArgs["sphere"] = sphereSubmesh;
  704.     geo->DrawArgs["cylinder"] = cylinderSubmesh;
  705.  
  706.     mGeometries[geo->Name] = std::move(geo);
  707. }
  708.  
  709. void CameraAndDynamicIndexingApp::BuildPSOs()
  710. {
  711.     D3D12_GRAPHICS_PIPELINE_STATE_DESC opaquePsoDesc;
  712.  
  713.     //
  714.     // PSO for opaque objects.
  715.     //
  716.     ZeroMemory(&opaquePsoDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
  717.     opaquePsoDesc.InputLayout = { mInputLayout.data(), (UINT)mInputLayout.size() };
  718.     opaquePsoDesc.pRootSignature = mRootSignature.Get();
  719.     opaquePsoDesc.VS = 
  720.     { 
  721.         reinterpret_cast<BYTE*>(mShaders["standardVS"]->GetBufferPointer()), 
  722.         mShaders["standardVS"]->GetBufferSize()
  723.     };
  724.     opaquePsoDesc.PS = 
  725.     { 
  726.         reinterpret_cast<BYTE*>(mShaders["opaquePS"]->GetBufferPointer()),
  727.         mShaders["opaquePS"]->GetBufferSize()
  728.     };
  729.     opaquePsoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
  730.     opaquePsoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
  731.     opaquePsoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
  732.     opaquePsoDesc.SampleMask = UINT_MAX;
  733.     opaquePsoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
  734.     opaquePsoDesc.NumRenderTargets = 1;
  735.     opaquePsoDesc.RTVFormats[0] = mBackBufferFormat;
  736.     opaquePsoDesc.SampleDesc.Count = m4xMsaaState ? 4 : 1;
  737.     opaquePsoDesc.SampleDesc.Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0;
  738.     opaquePsoDesc.DSVFormat = mDepthStencilFormat;
  739.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&opaquePsoDesc, IID_PPV_ARGS(&mPSOs["opaque"])));
  740. }
  741.  
  742. void CameraAndDynamicIndexingApp::BuildFrameResources()
  743. {
  744.     for(int i = 0; i < gNumFrameResources; ++i)
  745.     {
  746.         mFrameResources.push_back(std::make_unique<FrameResource>(md3dDevice.Get(),
  747.             1, (UINT)mAllRitems.size(), (UINT)mMaterials.size()));
  748.     }
  749. }
  750.  
  751. void CameraAndDynamicIndexingApp::BuildMaterials()
  752. {
  753.     auto bricks0 = std::make_unique<Material>();
  754.     bricks0->Name = "bricks0";
  755.     bricks0->MatCBIndex = 0;
  756.     bricks0->DiffuseSrvHeapIndex = 0;
  757.     bricks0->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  758.     bricks0->FresnelR0 = XMFLOAT3(0.02f, 0.02f, 0.02f);
  759.     bricks0->Roughness = 0.1f;
  760.  
  761.     auto stone0 = std::make_unique<Material>();
  762.     stone0->Name = "stone0";
  763.     stone0->MatCBIndex = 1;
  764.     stone0->DiffuseSrvHeapIndex = 1;
  765.     stone0->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  766.     stone0->FresnelR0 = XMFLOAT3(0.05f, 0.05f, 0.05f);
  767.     stone0->Roughness = 0.3f;
  768.  
  769.     auto tile0 = std::make_unique<Material>();
  770.     tile0->Name = "tile0";
  771.     tile0->MatCBIndex = 2;
  772.     tile0->DiffuseSrvHeapIndex = 2;
  773.     tile0->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  774.     tile0->FresnelR0 = XMFLOAT3(0.02f, 0.02f, 0.02f);
  775.     tile0->Roughness = 0.3f;
  776.  
  777.     auto crate0 = std::make_unique<Material>();
  778.     crate0->Name = "crate0";
  779.     crate0->MatCBIndex = 3;
  780.     crate0->DiffuseSrvHeapIndex = 3;
  781.     crate0->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  782.     crate0->FresnelR0 = XMFLOAT3(0.05f, 0.05f, 0.05f);
  783.     crate0->Roughness = 0.2f;
  784.     
  785.     mMaterials["bricks0"] = std::move(bricks0);
  786.     mMaterials["stone0"] = std::move(stone0);
  787.     mMaterials["tile0"] = std::move(tile0);
  788.     mMaterials["crate0"] = std::move(crate0);
  789. }
  790.  
  791. void CameraAndDynamicIndexingApp::BuildRenderItems()
  792. {
  793.     auto boxRitem = std::make_unique<RenderItem>();
  794.     XMStoreFloat4x4(&boxRitem->World, XMMatrixScaling(2.0f, 2.0f, 2.0f)*XMMatrixTranslation(0.0f, 1.0f, 0.0f));
  795.     XMStoreFloat4x4(&boxRitem->TexTransform, XMMatrixScaling(1.0f, 1.0f, 1.0f));
  796.     boxRitem->ObjCBIndex = 0;
  797.     boxRitem->Mat = mMaterials["crate0"].get();
  798.     boxRitem->Geo = mGeometries["shapeGeo"].get();
  799.     boxRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  800.     boxRitem->IndexCount = boxRitem->Geo->DrawArgs["box"].IndexCount;
  801.     boxRitem->StartIndexLocation = boxRitem->Geo->DrawArgs["box"].StartIndexLocation;
  802.     boxRitem->BaseVertexLocation = boxRitem->Geo->DrawArgs["box"].BaseVertexLocation;
  803.     mAllRitems.push_back(std::move(boxRitem));
  804.  
  805.     auto gridRitem = std::make_unique<RenderItem>();
  806.     gridRitem->World = MathHelper::Identity4x4();
  807.     XMStoreFloat4x4(&gridRitem->TexTransform, XMMatrixScaling(8.0f, 8.0f, 1.0f));
  808.     gridRitem->ObjCBIndex = 1;
  809.     gridRitem->Mat = mMaterials["tile0"].get();
  810.     gridRitem->Geo = mGeometries["shapeGeo"].get();
  811.     gridRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  812.     gridRitem->IndexCount = gridRitem->Geo->DrawArgs["grid"].IndexCount;
  813.     gridRitem->StartIndexLocation = gridRitem->Geo->DrawArgs["grid"].StartIndexLocation;
  814.     gridRitem->BaseVertexLocation = gridRitem->Geo->DrawArgs["grid"].BaseVertexLocation;
  815.     mAllRitems.push_back(std::move(gridRitem));
  816.  
  817.     XMMATRIX brickTexTransform = XMMatrixScaling(1.0f, 1.0f, 1.0f);
  818.     UINT objCBIndex = 2;
  819.     for(int i = 0; i < 5; ++i)
  820.     {
  821.         auto leftCylRitem = std::make_unique<RenderItem>();
  822.         auto rightCylRitem = std::make_unique<RenderItem>();
  823.         auto leftSphereRitem = std::make_unique<RenderItem>();
  824.         auto rightSphereRitem = std::make_unique<RenderItem>();
  825.  
  826.         XMMATRIX leftCylWorld = XMMatrixTranslation(-5.0f, 1.5f, -10.0f + i*5.0f);
  827.         XMMATRIX rightCylWorld = XMMatrixTranslation(+5.0f, 1.5f, -10.0f + i*5.0f);
  828.  
  829.         XMMATRIX leftSphereWorld = XMMatrixTranslation(-5.0f, 3.5f, -10.0f + i*5.0f);
  830.         XMMATRIX rightSphereWorld = XMMatrixTranslation(+5.0f, 3.5f, -10.0f + i*5.0f);
  831.  
  832.         XMStoreFloat4x4(&leftCylRitem->World, rightCylWorld);
  833.         XMStoreFloat4x4(&leftCylRitem->TexTransform, brickTexTransform);
  834.         leftCylRitem->ObjCBIndex = objCBIndex++;
  835.         leftCylRitem->Mat = mMaterials["bricks0"].get();
  836.         leftCylRitem->Geo = mGeometries["shapeGeo"].get();
  837.         leftCylRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  838.         leftCylRitem->IndexCount = leftCylRitem->Geo->DrawArgs["cylinder"].IndexCount;
  839.         leftCylRitem->StartIndexLocation = leftCylRitem->Geo->DrawArgs["cylinder"].StartIndexLocation;
  840.         leftCylRitem->BaseVertexLocation = leftCylRitem->Geo->DrawArgs["cylinder"].BaseVertexLocation;
  841.  
  842.         XMStoreFloat4x4(&rightCylRitem->World, leftCylWorld);
  843.         XMStoreFloat4x4(&rightCylRitem->TexTransform, brickTexTransform);
  844.         rightCylRitem->ObjCBIndex = objCBIndex++;
  845.         rightCylRitem->Mat = mMaterials["bricks0"].get();
  846.         rightCylRitem->Geo = mGeometries["shapeGeo"].get();
  847.         rightCylRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  848.         rightCylRitem->IndexCount = rightCylRitem->Geo->DrawArgs["cylinder"].IndexCount;
  849.         rightCylRitem->StartIndexLocation = rightCylRitem->Geo->DrawArgs["cylinder"].StartIndexLocation;
  850.         rightCylRitem->BaseVertexLocation = rightCylRitem->Geo->DrawArgs["cylinder"].BaseVertexLocation;
  851.  
  852.         XMStoreFloat4x4(&leftSphereRitem->World, leftSphereWorld);
  853.         leftSphereRitem->TexTransform = MathHelper::Identity4x4();
  854.         leftSphereRitem->ObjCBIndex = objCBIndex++;
  855.         leftSphereRitem->Mat = mMaterials["stone0"].get();
  856.         leftSphereRitem->Geo = mGeometries["shapeGeo"].get();
  857.         leftSphereRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  858.         leftSphereRitem->IndexCount = leftSphereRitem->Geo->DrawArgs["sphere"].IndexCount;
  859.         leftSphereRitem->StartIndexLocation = leftSphereRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  860.         leftSphereRitem->BaseVertexLocation = leftSphereRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  861.  
  862.         XMStoreFloat4x4(&rightSphereRitem->World, rightSphereWorld);
  863.         rightSphereRitem->TexTransform = MathHelper::Identity4x4();
  864.         rightSphereRitem->ObjCBIndex = objCBIndex++;
  865.         rightSphereRitem->Mat = mMaterials["stone0"].get();
  866.         rightSphereRitem->Geo = mGeometries["shapeGeo"].get();
  867.         rightSphereRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  868.         rightSphereRitem->IndexCount = rightSphereRitem->Geo->DrawArgs["sphere"].IndexCount;
  869.         rightSphereRitem->StartIndexLocation = rightSphereRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  870.         rightSphereRitem->BaseVertexLocation = rightSphereRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  871.  
  872.         mAllRitems.push_back(std::move(leftCylRitem));
  873.         mAllRitems.push_back(std::move(rightCylRitem));
  874.         mAllRitems.push_back(std::move(leftSphereRitem));
  875.         mAllRitems.push_back(std::move(rightSphereRitem));
  876.     }
  877.  
  878.     // All the render items are opaque.
  879.     for(auto& e : mAllRitems)
  880.         mOpaqueRitems.push_back(e.get());
  881. }
  882.  
  883. void CameraAndDynamicIndexingApp::DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems)
  884. {
  885.     UINT objCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(ObjectConstants));
  886.  
  887.     auto objectCB = mCurrFrameResource->ObjectCB->Resource();
  888.  
  889.     // For each render item...
  890.     for(size_t i = 0; i < ritems.size(); ++i)
  891.     {
  892.         auto ri = ritems[i];
  893.  
  894.         cmdList->IASetVertexBuffers(0, 1, &ri->Geo->VertexBufferView());
  895.         cmdList->IASetIndexBuffer(&ri->Geo->IndexBufferView());
  896.         cmdList->IASetPrimitiveTopology(ri->PrimitiveType);
  897.  
  898.         D3D12_GPU_VIRTUAL_ADDRESS objCBAddress = objectCB->GetGPUVirtualAddress() + ri->ObjCBIndex*objCBByteSize;
  899.  
  900.         // CD3DX12_GPU_DESCRIPTOR_HANDLE tex(mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  901.         // tex.Offset(ri->Mat->DiffuseSrvHeapIndex, mCbvSrvDescriptorSize);
  902.  
  903.         cmdList->SetGraphicsRootConstantBufferView(0, objCBAddress);
  904.  
  905.         cmdList->DrawIndexedInstanced(ri->IndexCount, 1, ri->StartIndexLocation, ri->BaseVertexLocation, 0);
  906.     }
  907. }
  908.  
  909. std::array<const CD3DX12_STATIC_SAMPLER_DESC, 6> CameraAndDynamicIndexingApp::GetStaticSamplers()
  910. {
  911.     // Applications usually only need a handful of samplers.  So just define them all up front
  912.     // and keep them available as part of the root signature.  
  913.  
  914.     const CD3DX12_STATIC_SAMPLER_DESC pointWrap(
  915.         0, // shaderRegister
  916.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  917.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  918.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  919.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  920.  
  921.     const CD3DX12_STATIC_SAMPLER_DESC pointClamp(
  922.         1, // shaderRegister
  923.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  924.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  925.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  926.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  927.  
  928.     const CD3DX12_STATIC_SAMPLER_DESC linearWrap(
  929.         2, // shaderRegister
  930.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  931.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  932.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  933.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  934.  
  935.     const CD3DX12_STATIC_SAMPLER_DESC linearClamp(
  936.         3, // shaderRegister
  937.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  938.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  939.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  940.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  941.  
  942.     const CD3DX12_STATIC_SAMPLER_DESC anisotropicWrap(
  943.         4, // shaderRegister
  944.         D3D12_FILTER_ANISOTROPIC, // filter
  945.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  946.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  947.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressW
  948.         0.0f,                             // mipLODBias
  949.         8);                               // maxAnisotropy
  950.  
  951.     const CD3DX12_STATIC_SAMPLER_DESC anisotropicClamp(
  952.         5, // shaderRegister
  953.         D3D12_FILTER_ANISOTROPIC, // filter
  954.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  955.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  956.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressW
  957.         0.0f,                              // mipLODBias
  958.         8);                                // maxAnisotropy
  959.  
  960.     return { 
  961.         pointWrap, pointClamp,
  962.         linearWrap, linearClamp, 
  963.         anisotropicWrap, anisotropicClamp };
  964. }
  965.  
  966.